#!/usr/bin/python
# -*- coding:UTF8 -*-
class Animal():

    def __init__(self, name):
        self.name = name
        self._secret = 'the "lie" hid in friend word'

    def talk(self, voice):
        print(f'{self.name} is talk using {voice}')

    def __kongfu(self):
        print(f'{self._secret}这是我的独门绝技。不可外传')


"""
子类继承父类
会将父类中的构造器和 定义的方法继承过来
私有:父类中如果有些方法或者属性不希望被子类继承，可以在 属性名 或者 方法名 前边添加 __ 即可
"""


class cats(Animal):

    def color(self, color):
        print(f'{self.name} is {color} cat')


cute_cat = cats('coco')
cute_cat.talk('miao~miao~')
cute_cat.color('pink')

# cute_cat.secret
dog = Animal('hh')

print(cats.__mro__)
print(''.center(50, '='))


# 函数的参数
def myself(name, age, *hobby, **other):
    """

    :param name:
    :param age:
    :param hobby:
    :param other:
    :return:
    """
    print(f'我的名字是{name},今年{age}岁')
    print(f'我的爱好是{hobby}')
    print(f'其他信息{other}')


myself('小米', '25', 'work', 'read', 'write')
myself('小明', '32', 'drink', goodat='apitest')
print(''.center(50, '='))

# 面向对象  【单继承】
"""
继承的概念：如果两个类存在父子级继承的关系，子类即便没有任何的属性和方法，那么用子类继承了某一个父类，并且此子类创建了一个对象，那么这个对象就拥有父类当中的所有属性和方法的使用权
就像生活中子女继承父母财产一样。
"""


class 小头爸爸(object):  # 在Python中，所有类默认继承object类，object类是顶级类或基类；其它子类叫做派生类。
    # 实例属性
    def __init__(self):
        self.age = 30

    # 实例方法
    def 实例方法(self):
        print(f'小头爸爸的年龄是{self.age}岁')


class 大头儿子(小头爸爸):
    pass  # 伪代码，占位子用的


# 实例化对象
对象1 = 大头儿子()
对象1.实例方法()
print(大头儿子.__mro__)  # 用于查看继承关系
print(''.center(50, '='))
# 面向对象  【多继承】
"""
所谓多继承：就是一个类同时继承了多个父类。
注意：当一个类有多个父类的时候，默认使用第一个父类的同名属性和方法。
"""


class 叶问(object):
    def __init__(self):
        self.技能 = '咏春拳'

    def 实例方法(self):
        print(f'使用{self.技能}攻击')


class 李小龙(叶问):
    def __init__(self):
        self.技能 = '截拳道'

    def 实例方法(self):
        print(f'使用{self.技能}攻击')


class 成龙(李小龙):
    def __init__(self):
        self.技能 = '蛇拳'

    def 实例方法(self):
        print(f'使用{self.技能}攻击')


class 张阿牛(成龙):
    pass


# 实例化对象
对象1 = 张阿牛()
对象1.实例方法()
print(张阿牛.__mro__)
print(''.center(50, '='))


# 子类和父类具有同名属性和方法时:默认使用子类的同名属性和方法。
class YeWen():
    def __init__(self):
        self.jineng = '咏春拳'

    def jinengfangfa(self):
        print(f'使用{self.jineng}攻击')


class LiXiaoLong():
    def __init__(self):
        self.jineng = '截拳道'

    def shilifangfa(self):
        print(f'使用{self.jineng}攻击')


class ZengANiu(LiXiaoLong):
    def __init__(self):
        self.jineng = '健身'

    def shilifangfa(self):
        print(f'日常{self.jineng}')


duixiang1 = ZengANiu()
duixiang1.shilifangfa()
print(''.center(50, '='))


# 子类和父类具有同名属性和方法时:既想调用父类的属性方法，又想调用子类的
class YeWen():
    def __init__(self):
        self.jineng = '咏春拳'

    def 实例方法(self):
        print(f'使用{self.jineng}攻击')


class LiXiaoLong:
    def __init__(self):
        self.jineng = '截拳道'

    def 实例方法(self):
        print(f'使用{self.jineng}攻击')


class ZengANiu(LiXiaoLong, YeWen):
    def __init__(self):
        self.jineng = '健身'

    def 实例方法(self):
        self.__init__()  # 如果是先调用了父类的属性和方法，父类属性会覆盖子类属性，故在调用前，先调用自己子类的初始化。
        print(f'日常{self.jineng}')

    def YeWen_实例方法(self):
        YeWen.__init__(self)  # 调用父类的属性和方法
        YeWen.实例方法(self)

    def LiXiaoLong_实例方法(self):
        LiXiaoLong.__init__(self)
        LiXiaoLong.实例方法(self)


对象1 = ZengANiu()
对象1.实例方法()
对象1.YeWen_实例方法()
对象1.LiXiaoLong_实例方法()
print(''.center(50, '*'))

# 面向对象  【多层继承】
"""
多层继承容易导致代码混乱，所以当不确定是否必须使用的时候，请尽量避免使用它，因为有些时候会出现不可预见的BUG。
"""


class YeWen(object):
    def __init__(self):
        self.jineng = '咏春拳'

    def 实例方法(self):
        print(f'使用{self.jineng}攻击')


class LiXiaoLong(object):
    def __init__(self):
        self.jineng = '截拳道'

    def 实例方法(self):
        print(f'使用{self.jineng}攻击')


class ChengLong(YeWen, LiXiaoLong):
    def __init__(self):
        self.jineng = '蛇拳'

    def 实例方法(self):
        self.__init__()
        print(f'使用{self.jineng}攻击')

    def yewen_实例方法(self):
        YeWen.__init__(self)
        YeWen.实例方法(self)

    def lixiaolong_实例方法(self):
        LiXiaoLong.__init__(self)
        LiXiaoLong.实例方法(self)


class ZengANiu(ChengLong):
    pass


对象1 = ZengANiu()
对象1.实例方法()
print(对象1.jineng)
对象1.yewen_实例方法()
对象1.lixiaolong_实例方法()
print(ZengANiu.__mro__)
print(''.center(50, '%'))


# 面向对象 类之间无法继承又得调用时用组合 【组合】(了解)
class YeWen(object):
    def __init__(self, x):
        self.gongfu = x


class LiXiaoLong(object):
    def __init__(self, x):
        self.gongfu = x


class XiangGang(object):
    def __init__(self, x, y):
        self.YeWen = YeWen(x)  # 直接把类放进去实例化
        self.LiXiaoLong = LiXiaoLong(y)

    def gongfu(self):
        # 格式化字符串：self.类名.属性
        print(f'在香港，叶问使用功夫{self.YeWen.gongfu}次，李小龙使用功夫{self.LiXiaoLong.gongfu}次')


duixiang1 = XiangGang(2, 5)
duixiang1.gongfu()
print(''.center(50, '-'))
